﻿//------------------------------------------------------------------------------
// <copyright file="CommerceServerRequestTemplateGenerator.cs" company="CommerceServer.net, Inc">
//    (c) 2012 CommerceServer.net, Inc. and its affiliates. All rights reserved.
// </copyright>
// <summary></summary>
//------------------------------------------------------------------------------ 
namespace CommerceServerContrib.CodeGeneration
{
    using CommerceServer.Foundation;
    using CommerceServer.Foundation.RequestTemplates;
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;

    public class CommerceServerRequestTemplateGenerator : Foundation
    {
        private const string ArgumentSummaryConstant = "ArgumentSummary";

        public CommerceServerRequestTemplateGenerator(string channel, string userLocale, string userUILocale)
            : base(channel, userLocale, userUILocale)
        {
        }

        public CommerceServerRequestTemplateGenerator()
            : base()
        {
        }

        public virtual List<CommerceEntity> GetRequestTemplates()
        {
            var queryTemplates = new CommerceQuery<CommerceEntity>("RequestTemplate");
            var response = this.InvokeFoundation(queryTemplates.ToRequest());
            var queryResponse = response.OperationResponses[0] as CommerceQueryOperationResponse;

            foreach (var entity in queryResponse.CommerceEntities)
            {
                var requestTemplate = entity as RequestTemplate;
                this.ProcessOperation(requestTemplate, requestTemplate.Operations);
            }

            return queryResponse.CommerceEntities;
        }

        protected virtual void ProcessOperation(RequestTemplate requestTemplate, List<Operation> operations)
        {
            foreach (var operation in operations)
            {
                var arguments = requestTemplate.GetPropertyValue(ArgumentSummaryConstant) as List<RequestTemplatePropertyDefinition>;

                if (arguments == null)
                {
                    arguments = new List<RequestTemplatePropertyDefinition>();
                    requestTemplate.SetPropertyValue(ArgumentSummaryConstant, arguments);
                }

                if (operation.Search != null && operation.Search.Count > 0)
                {
                    foreach (SearchArgument item in operation.Search)
                    {
                        this.BuildPropertyDefinition(arguments, item, RequestTemplateParameterType.Search);
                    }
                }

                if (operation.PropertiesToSet != null && operation.PropertiesToSet.Count > 0)
                {
                    foreach (PropertyToSetArgument item in operation.PropertiesToSet)
                    {
                        this.BuildPropertyDefinition(arguments, item, RequestTemplateParameterType.PropertiesToSet);
                    }
                }

                if (operation.Sort != null && operation.Sort.Count > 0)
                {
                    foreach (SortArgument item in operation.Sort)
                    {
                        this.BuildPropertyDefinition(arguments, item, RequestTemplateParameterType.Sort);
                    }
                }

                if (operation.Options != null && operation.Options.Count > 0)
                {
                    foreach (OptionArgument item in operation.Options)
                    {
                        this.BuildPropertyDefinition(arguments, item, RequestTemplateParameterType.Option);
                    }
                }

                if (operation.RelatedOperations != null && operation.RelatedOperations.Count > 0)
                {
                    this.ProcessOperation(requestTemplate, operation.RelatedOperations);
                }
            }
        }

        protected virtual void BuildPropertyDefinition(
            List<RequestTemplatePropertyDefinition> arguments, 
            BaseArgument item, 
            RequestTemplateParameterType requestTemplateParameterType)
        {
            var designTimeType = "string";
            var alias = item.ShortName.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries)[1];
            var parameterName = alias.ToString().ToLower(CultureInfo.InvariantCulture)[0] + alias.Remove(0, 1);

            if (item.PropertyMetadata != null)
            {
                designTimeType = item.PropertyMetadata.DataType.Value.ToString();
            }

            var existingArg = arguments.Where(s => s.Name == parameterName).FirstOrDefault();

            if (existingArg != null)
            {
                if (existingArg.ArgumentType == requestTemplateParameterType)
                {
                    return;
                }
                else
                {
                    var prefix = requestTemplateParameterType.ToString().ToLower(CultureInfo.InvariantCulture)[0] + requestTemplateParameterType.ToString().Remove(0, 1);
                    parameterName = prefix + parameterName;
                }
            }

            var arg = new RequestTemplatePropertyDefinition(
                requestTemplateParameterType, 
                parameterName,
                designTimeType,
                alias);

            arguments.Add(arg);
        }
    }
}
